﻿namespace MicroCloud.Api.Identity.Areas.Admin.Controllers.Identity
{
    /// <summary>
    /// 组织机构管理
    /// </summary>
    [Description("组织机构管理")]
    [ModuleInfo(Code = "Organization", Name = "组织机构管理", OrderNo = 1, Position = "Identity", PositionName = "认证模块")]
    public class OrganizationController : AdminControllerBase
    {
        #region "属性"
        #region "获取 提供查询组织机构存储中的组织机构"
        /// <summary>
        /// 获取 提供查询组织机构存储中的组织机构
        /// </summary>
        protected IQueryableOrganizationStore<Organization> QueryableOrganizationStore => ServiceProvider.GetService<IQueryableOrganizationStore<Organization>>();
        #endregion
        #region "获取 身份认证模块"
        /// <summary>
        /// 获取 身份认证模块
        /// </summary>
        protected IIdentityContract IdentityContract => ServiceProvider.GetService<IIdentityContract>();
        #endregion

        #region "获取 组织机构仓储模型"
        /// <summary>
        /// 获取 组织机构仓储模型
        /// </summary>
        protected IRepository<Organization, long> OrganizationRepository => ServiceProvider.GetService<IRepository<Organization, long>>();
        #endregion
        #region "获取 组织机构证照仓储模型"
        /// <summary>
        /// 获取 组织机构证照仓储模型
        /// </summary>
        protected IRepository<OrganizationPortfolio, long> OrganizationPortfolioRepository => ServiceProvider.GetService<IRepository<OrganizationPortfolio, long>>();
        #endregion
        #region "获取 组织机构详情仓储模型"
        /// <summary>
        /// 获取 组织机构详情仓储模型
        /// </summary>
        protected IRepository<OrganizationDetail, long> OrganizationDetailRepository => ServiceProvider.GetService<IRepository<OrganizationDetail, long>>();
        #endregion

        #endregion

        #region "Action方法"
        #region "读取组织机构"
        /// <summary>
        /// 读取组织机构
        /// </summary>
        /// <param name="request">分页请求</param>
        /// <returns>组织机构页列表</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(GetTreeNodesExclude))]
        [Description("读取")]
        public virtual PageData<OrganizationOutputDto> Read(PageRequest request)
        {
            Check.NotNull(request, nameof(request));
            IFunction function = this.GetExecuteFunction();

            request.AddDefaultSortCondition(new SortCondition("TreePathString", ListSortDirection.Ascending));
            request.AddDefaultSortCondition(new SortCondition("OrderNo", ListSortDirection.Ascending));

            Func<Organization, bool> updateFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Update).Compile();
            Func<Organization, bool> deleteFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Delete).Compile();
            Expression<Func<Organization, bool>> predicate = FilterService.GetExpression<Organization>(request.FilterGroup);

            PageResult<OrganizationOutputDto> page;
            using (var scope = ServiceProvider.CreateScope())
            {
                var userRepository = scope.ServiceProvider.GetService<IRepository<User, long>>();

                page = CacheService.ToPageCache(QueryableOrganizationStore.Organizations, predicate, request.PageCondition, m => new
                {
                    O = m,
                    D = m.Detail,
                    Creator = GetUser(userRepository, m.CreatorId),
                    Updater = GetUser(userRepository, m.UpdaterId),
                }, function).ToPageResult(data => data.Select(m => new OrganizationOutputDto(m.O, m.D)
                {
                    CreatorName = m.Creator.UserName,
                    CreatorNickname = m.Creator.NickName,
                    UpdaterName = m.Updater.UserName,
                    UpdaterNickname = m.Updater.NickName,
                    Updatable = updateFunc(m.O),
                    Deletable = deleteFunc(m.O)
                }).ToArray());

            }

            return page.ToPageData();
        }
        #endregion
        #region "读取组织机构节点"
        /// <summary>
        /// 读取组织机构节点
        /// </summary>
        /// <param name="request">分页请求</param>
        /// <returns>组织机构节点页列表</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(GetTreeNodesExclude))]
        [Description("读取节点")]
        public virtual PageData<OrganizationNodeDto> ReadNode(PageRequest request)
        {
            Check.NotNull(request, nameof(request));
            IFunction function = this.GetExecuteFunction();

            request.AddDefaultSortCondition(new SortCondition("TreePathString", ListSortDirection.Ascending));
            request.AddDefaultSortCondition(new SortCondition("OrderNo", ListSortDirection.Ascending));

            Func<Organization, bool> updateFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Update).Compile();
            Func<Organization, bool> deleteFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Delete).Compile();
            Expression<Func<Organization, bool>> predicate = FilterService.GetExpression<Organization>(request.FilterGroup);

            PageResult<OrganizationNodeDto> page;
            using (var scope = ServiceProvider.CreateScope())
            {
                var userRepository = scope.ServiceProvider.GetService<IRepository<User, long>>();

                page = CacheService.ToPageCache(QueryableOrganizationStore.Organizations, predicate, request.PageCondition, m => new
                {
                    O = m,
                    D = m.Detail,
                    Creator = GetUser(userRepository, m.CreatorId),
                    Updater = GetUser(userRepository, m.UpdaterId),
                }, function).ToPageResult(data => data.Select(m => new OrganizationNodeDto(m.O, m.D)
                {
                    CreatorName = m.Creator.UserName,
                    CreatorNickname = m.Creator.NickName,
                    UpdaterName = m.Updater.UserName,
                    UpdaterNickname = m.Updater.NickName,
                    Updatable = updateFunc(m.O),
                    Deletable = deleteFunc(m.O)
                }).ToArray());

            }

            return page.ToPageData();
        }
        #endregion
        #region "读取组织机构树"
        /// <summary>
        /// 读取组织机构树
        /// </summary>
        /// <param name="request">分页请求</param>
        /// <returns>组织机构树页列表</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(GetTreeNodesExclude))]
        [Description("读取树")]
        public virtual PageData<OrganizationTreeNodeDto> ReadTreeNode(PageRequest request)
        {
            Check.NotNull(request, nameof(request));
            IFunction function = this.GetExecuteFunction();

            request.AddDefaultSortCondition(new SortCondition("TreePathString", ListSortDirection.Ascending));
            request.AddDefaultSortCondition(new SortCondition("OrderNo", ListSortDirection.Ascending));

            Func<Organization, bool> updateFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Update).Compile();
            Func<Organization, bool> deleteFunc = FilterService.GetDataFilterExpression<Organization>(null, DataAuthOperation.Delete).Compile();
            Expression<Func<Organization, bool>> predicate = FilterService.GetExpression<Organization>(request.FilterGroup);

            PageResult<OrganizationNodeDto> page;
            using (var scope = ServiceProvider.CreateScope())
            {
                var userRepository = scope.ServiceProvider.GetService<IRepository<User, long>>();

                page = CacheService.ToPageCache(QueryableOrganizationStore.Organizations, predicate, request.PageCondition, m => new
                {
                    O = m,
                    D = m.Detail,
                    Creator = GetUser(userRepository, m.CreatorId),
                    Updater = GetUser(userRepository, m.UpdaterId),
                }, function).ToPageResult(data => data.Select(m => new OrganizationNodeDto(m.O, m.D)
                {
                    CreatorName = m.Creator.UserName,
                    CreatorNickname = m.Creator.NickName,
                    UpdaterName = m.Updater.UserName,
                    UpdaterNickname = m.Updater.NickName,
                    Updatable = updateFunc(m.O),
                    Deletable = deleteFunc(m.O)
                }).ToArray());

            }

            var treeNodes = page.Data.ToTreeNodes();
            PageResult<OrganizationTreeNodeDto> treeNodePage = new(treeNodes.ToArray(), page.Total);

            return treeNodePage.ToPageData();
        }
        #endregion

        #region "获取组织机构"
        /// <summary>
        /// 获取组织机构
        /// </summary>
        /// <param name="organizationIds">组织机构编号</param>
        /// <returns>组织机构树数据</returns>
        [HttpPost]
        [LoggedIn]
        [ModuleInfo]
        [Description("获取")]
        public virtual List<OrganizationDto> GetOrganizations(params long[] organizationIds)
        {
            Check.NotNull(organizationIds, nameof(organizationIds));

            IFunction function = this.GetExecuteFunction();

            Expression<Func<Organization, bool>> exp = m => organizationIds.Contains(m.Id);
            List<OrganizationDto> dtos = CacheService.ToCacheList(IdentityContract.Organizations, exp, o => new OrganizationDto(o, o.Portfolio, o.Detail), function);

            return dtos;
        }
        #endregion
        #region "获取组织机构节点"
        /// <summary>
        /// 获取组织机构节点
        /// </summary>
        /// <param name="organizationIds">组织机构编号</param>
        /// <returns>组织机构节点数据</returns>
        [HttpPost]
        [LoggedIn]
        [ModuleInfo]
        [Description("获取节点")]
        public virtual List<OrganizationNodeSimple> GetOrganizationNodes(params long[] organizationIds)
        {
            Check.NotNull(organizationIds, nameof(organizationIds));

            IFunction function = this.GetExecuteFunction();
            long[] checkOrganizationIds = organizationIds;

            Expression<Func<Organization, bool>> exp2 = m => true;
            List<OrganizationNodeSimple> nodes = CacheService.ToCacheList<Organization, OrganizationNodeSimple>(IdentityContract.Organizations, exp2, function);

            nodes.ForEach(m => m.IsChecked = checkOrganizationIds.Contains(m.Id));
            return nodes;
        }
        #endregion
        #region "获取排除指定编号后的组织机构树"
        /// <summary>
        /// 获取排除指定编号后的组织机构树
        /// </summary>
        /// <param name="organizationId">组织机构编号</param>
        /// <returns>组织机构树数据</returns>
        [HttpGet]
        [LoggedIn]
        [ModuleInfo]
        [Description("获取排除指定编号后的树")]
        public virtual OrganizationTreeNode[] GetTreeNodesExclude(long organizationId)
        {
            //Check.GreaterThan(organizationId, nameof(organizationId), 0);

            var entity = QueryableOrganizationStore.Organizations.FirstOrDefault(o => Equals(o.Id, organizationId));
            var treePathString = entity == null ? "" : entity.TreePathString;

            IFunction function = this.GetExecuteFunction();
            //Expression<Func<Organization, bool>> predicate = m => !m.TreePathString.StartsWith(treePathString) || treePathString.IsMissing();
            Expression<Func<Organization, bool>> predicate = m => treePathString.IsMissing() || !EF.Functions.Like(m.TreePathString, $"{treePathString}%", @"\");
            SortCondition[] sortConditions = new SortCondition[] { new("ParentId"), new("OrderNo") };

            var nodeList = CacheService.ToCacheList(QueryableOrganizationStore.Organizations.Sort(sortConditions), predicate, m => m.MapTo<Organization, OrganizationNode>(), function);

            var treeNodes = nodeList.ToTreeNodes();
            return treeNodes.ToArray();
        }
        #endregion

        #region "读取组织机构[用户]树"
        /// <summary>
        /// 读取组织机构[用户]树
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns>组织机构[用户]树数据</returns>
        [HttpGet]
        [ModuleInfo]
        [Description("读取[用户]树")]
        public virtual List<OrganizationRoleUserNode> ReadUserOrganizations(long userId)
        {
            Check.GreaterThan(userId, nameof(userId), 0);

            IFunction function = this.GetExecuteFunction();

            Expression<Func<UserOrganization, bool>> exp = m => m.UserId.Equals(userId);
            var organizationUsers = CacheService.ToCacheList(IdentityContract.UserOrganizations, exp, m => new { m.UserId, m.OrganizationId, m.Administrator, m.Leader }, function);

            //Expression<Func<Organization, bool>> exp2 = m => !m.IsLocked;
            Expression<Func<Organization, bool>> exp2 = m => true;
            var nodes = CacheService.ToCacheList(IdentityContract.Organizations, exp2, m => m.MapTo<Organization, OrganizationNode>().MapTo<OrganizationNode, OrganizationRoleUserNode>(), function);
            nodes.ForEach(m =>
            {
                m.IsChecked = organizationUsers.Exists(o => Equals(o.OrganizationId, m.Id.CastTo<long>()));
                m.Administrator = organizationUsers.FirstOrDefault(o => Equals(o.OrganizationId, m.Id.CastTo<long>()))?.Administrator == true;
                m.Leader = organizationUsers.FirstOrDefault(o => Equals(o.OrganizationId, m.Id.CastTo<long>()))?.Leader == true;
            });

            ////树形转换
            //List<OrganizationRoleUserNode> treeNodes = new();
            //var parentNodeList = nodes.Where(m => m.ParentId.IsMissing() || !nodes.Exists(o => Equals(o.Id, m.ParentId)));
            //foreach (var parentNode in parentNodeList)
            //{
            //    var treeNode = new OrganizationRoleUserNode
            //    {
            //        Id = parentNode.Id,
            //        Avatar = parentNode.Avatar,
            //        Type = parentNode.Type,
            //        Name = parentNode.Name,
            //        NameFrgn = parentNode.NameFrgn,
            //        Address = parentNode.Address,
            //        AddressFrgn = parentNode.AddressFrgn,
            //        PrintHeader = parentNode.PrintHeader,
            //        PrintHeaderFrgn = parentNode.PrintHeaderFrgn,
            //        ReptName = parentNode.ReptName,
            //        ReptNameFrgn = parentNode.ReptNameFrgn,
            //        Remark = parentNode.Remark,

            //        OrderNo = parentNode.OrderNo,
            //        TreePathString = parentNode.TreePathString,

            //        ParentId = parentNode.ParentId,
            //        EnableLogin = parentNode.EnableLogin,
            //        IsDefault = parentNode.IsDefault,
            //        IsSystem = parentNode.IsSystem,
            //        IsLocked = parentNode.IsLocked,
            //        CreatedTime = parentNode.CreatedTime,
            //        IsChecked = parentNode.IsChecked,
            //        Administrator = parentNode.Administrator,
            //        Leader = parentNode.Leader,
            //    };
            //    treeNode.Items = ConvertOrganizationRoleUserNodeToTree(treeNode, nodes);
            //    treeNodes.Add(treeNode);
            //}

            return nodes;
        }
        #endregion
        #region "读取组织机构[角色]树"
        /// <summary>
        /// 读取组织机构[角色]树
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>组织机构[角色]树数据</returns>
        [HttpGet]
        [ModuleInfo]
        [Description("读取[角色]树")]
        public virtual List<OrganizationRoleUserNode> ReadRoleOrganizations(long roleId)
        {
            Check.GreaterThan(roleId, nameof(roleId), 0);

            IFunction function = this.GetExecuteFunction();

            Expression<Func<RoleOrganization, bool>> exp = m => m.RoleId.Equals(roleId);
            var organizationRoles = CacheService.ToCacheList(IdentityContract.RoleOrganizations, exp, m => new { m.RoleId, m.OrganizationId, m.Administrator, m.Leader }, function);

            //Expression<Func<Organization, bool>> exp2 = m => !m.IsLocked;
            Expression<Func<Organization, bool>> exp2 = m => true;
            var nodes = CacheService.ToCacheList(IdentityContract.Organizations, exp2, m => m.MapTo<Organization, OrganizationNode>().MapTo<OrganizationNode, OrganizationRoleUserNode>(), function);
            nodes.ForEach(m =>
            {
                m.IsChecked = organizationRoles.Exists(o => Equals(o.OrganizationId, m.Id.CastTo<long>()));
                m.Administrator = organizationRoles.FirstOrDefault(o => Equals(o.OrganizationId, m.Id.CastTo<long>()))?.Administrator == true;
                m.Leader = organizationRoles.FirstOrDefault(o => Equals(o.OrganizationId, m.Id.CastTo<long>()))?.Leader == true;
            });

            ////树形转换
            //List<OrganizationRoleUserNode> treeNodes = new();
            //var parentNodeList = nodes.Where(m => m.ParentId.IsMissing() || !nodes.Exists(o => Equals(o.Id, m.ParentId)));
            //foreach (var parentNode in parentNodeList)
            //{
            //    var treeNode = new OrganizationRoleUserNode
            //    {
            //        Id = parentNode.Id,
            //        Avatar = parentNode.Avatar,
            //        Type = parentNode.Type,
            //        Name = parentNode.Name,
            //        NameFrgn = parentNode.NameFrgn,
            //        Address = parentNode.Address,
            //        AddressFrgn = parentNode.AddressFrgn,
            //        PrintHeader = parentNode.PrintHeader,
            //        PrintHeaderFrgn = parentNode.PrintHeaderFrgn,
            //        ReptName = parentNode.ReptName,
            //        ReptNameFrgn = parentNode.ReptNameFrgn,
            //        Remark = parentNode.Remark,

            //        OrderNo = parentNode.OrderNo,
            //        TreePathString = parentNode.TreePathString,

            //        ParentId = parentNode.ParentId,
            //        EnableLogin = parentNode.EnableLogin,
            //        IsDefault = parentNode.IsDefault,
            //        IsSystem = parentNode.IsSystem,
            //        IsLocked = parentNode.IsLocked,
            //        CreatedTime = parentNode.CreatedTime,
            //        IsChecked = parentNode.IsChecked,
            //        Administrator = parentNode.Administrator,
            //        Leader = parentNode.Leader,
            //    };
            //    treeNode.Items = ConvertOrganizationRoleUserNodeToTree(treeNode, nodes);
            //    treeNodes.Add(treeNode);
            //}

            return nodes;
        }
        #endregion

        #region "新增组织机构"
        /// <summary>
        /// 新增组织机构
        /// </summary>
        /// <param name="dtos">新增组织机构信息</param>
        /// <returns>JSON操作结果</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(Read))]
        [DependOnFunction(nameof(ReadNode))]
        [DependOnFunction(nameof(ReadTreeNode))]
        [UnitOfWork]
        [Description("新增")]
        public virtual async Task<AjaxResult> Create(params OrganizationInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            List<string> names = new();
            foreach (var dto in dtos)
            {
                var organization = dto.MapTo<OrganizationInputDto, Organization>();
                var result = await QueryableOrganizationStore.CreateAsync(organization);
                if (!result.Succeeded)
                {
                    return result.ToAjaxResult();
                }
                //电子证照
                var portfolio = organization.Portfolio ?? new OrganizationPortfolio();
                portfolio.OrganizationId = organization.Id;
                portfolio.Avatar = dto.Avatar.IsMissing() ? StaticHelper.GetImgBase64String(ImageName.OrgLogo) : dto.Avatar;
                portfolio.Signature = dto.Signature;
                var result2 = await OrganizationPortfolioRepository.InsertOrUpdateAsync(new OrganizationPortfolio[] { portfolio });
                if (!result2.Succeeded)
                {
                    return result2.ToAjaxResult();
                }
                //详细信息
                var detail = organization.Detail ?? new OrganizationDetail();
                detail.OrganizationId = organization.Id;
                detail.NameFrgn = dto.NameFrgn;
                detail.Address = dto.Address;
                detail.AddressFrgn = dto.AddressFrgn;
                detail.PrintHeader = dto.PrintHeader;
                detail.PrintHeaderFrgn = dto.PrintHeaderFrgn;
                detail.ReptName = dto.ReptName;
                detail.ReptNameFrgn = dto.ReptNameFrgn;
                detail.Remark = dto.Remark;
                result2 = await OrganizationDetailRepository.InsertOrUpdateAsync(new OrganizationDetail[] { detail });
                if (!result2.Succeeded)
                {
                    return result2.ToAjaxResult();
                }

                names.Add(organization.Name);
                dto.Id = organization.Id;
            }
            return AjaxResult.Success(dtos, I18N.T("组织机构 {0} 创建成功", names.ExpandAndToString()));
        }
        #endregion
        #region "更新组织机构"
        /// <summary>
        /// 更新组织机构
        /// </summary>
        /// <param name="dtos">更新组织机构信息</param>
        /// <returns>JSON操作结果</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(Read))]
        [DependOnFunction(nameof(ReadNode))]
        [DependOnFunction(nameof(ReadTreeNode))]
        [UnitOfWork]
        [Description("更新")]
        public virtual async Task<AjaxResult> Update(params OrganizationInputDto[] dtos)
        {
            Check.NotNull(dtos, nameof(dtos));
            List<string> names = new();
            foreach (var dto in dtos)
            {
                var organization = OrganizationRepository.QueryAsNoTracking(o => o.Portfolio, o => o.Detail).Where(o => o.Id == dto.Id).FirstOrDefault();
                organization = dto.MapTo(organization);
                var result = await QueryableOrganizationStore.UpdateAsync(organization);
                if (!result.Succeeded)
                {
                    return result.ToAjaxResult();
                }
                //电子证照
                var portfolio = organization.Portfolio ?? new OrganizationPortfolio();
                //var portfolio = OrganizationPortfolioRepository.QueryAsNoTracking(o => o.OrganizationId == organization.Id).FirstOrDefault() ?? new OrganizationPortfolio();
                portfolio.OrganizationId = organization.Id;
                portfolio.Avatar = dto.Avatar.IsMissing() ? StaticHelper.GetImgBase64String(ImageName.OrgLogo) : dto.Avatar;
                portfolio.Signature = dto.Signature;
                var result2 = await OrganizationPortfolioRepository.InsertOrUpdateAsync(new OrganizationPortfolio[] { portfolio });
                if (!result2.Succeeded)
                {
                    return result2.ToAjaxResult();
                }
                //详细信息
                var detail = organization.Detail ?? new OrganizationDetail();
                //var detail = OrganizationDetailRepository.QueryAsNoTracking(o => o.OrganizationId == organization.Id).FirstOrDefault() ?? new OrganizationDetail();
                detail.OrganizationId = organization.Id;
                detail.NameFrgn = dto.NameFrgn;
                detail.Address = dto.Address;
                detail.AddressFrgn = dto.AddressFrgn;
                detail.PrintHeader = dto.PrintHeader;
                detail.PrintHeaderFrgn = dto.PrintHeaderFrgn;
                detail.ReptName = dto.ReptName;
                detail.ReptNameFrgn = dto.ReptNameFrgn;
                detail.Remark = dto.Remark;
                result2 = await OrganizationDetailRepository.InsertOrUpdateAsync(new OrganizationDetail[] { detail });
                if (!result2.Succeeded)
                {
                    return result2.ToAjaxResult();
                }

                names.Add(organization.Name);
            }
            return AjaxResult.Success(I18N.T("组织机构 {0} 更新成功", names.ExpandAndToString()));
        }
        #endregion
        #region "删除组织机构"
        /// <summary>
        /// 删除组织机构
        /// </summary>
        /// <param name="ids">要删除的组织机构编号</param>
        /// <returns>JSON操作结果</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(Read))]
        [DependOnFunction(nameof(ReadNode))]
        [DependOnFunction(nameof(ReadTreeNode))]
        [UnitOfWork]
        [Description("删除")]
        public virtual async Task<AjaxResult> Delete(params long[] ids)
        {
            Check.NotNull(ids, nameof(ids));
            List<string> names = new();
            foreach (var id in ids)
            {
                var orgId = id.ToString();
                Organization organizationEntity = await QueryableOrganizationStore.FindByIdAsync(orgId);
                var result = await QueryableOrganizationStore.DeleteAsync(organizationEntity);
                if (!result.Succeeded)
                {
                    return result.ToAjaxResult();
                }
                names.Add(organizationEntity.Name);
            }
            return AjaxResult.Success(I18N.T("组织机构 {0} 删除成功", names.ExpandAndToString()));
        }
        #endregion

        #region "设置组织机构用户"
        /// <summary>
        /// 设置组织机构用户
        /// </summary>
        /// <param name="dto">组织机构用户信息</param>
        /// <returns>JSON操作结果</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(Read))]
        [DependOnFunction(nameof(ReadNode))]
        [DependOnFunction(nameof(ReadTreeNode))]
        [DependOnFunction(nameof(ReadUserOrganizations))]
        [UnitOfWork]
        [Description("设置用户")]
        public virtual async Task<AjaxResult> SetUsers(OrganizationSetUserDto dto)
        {
            Check.NotNull(dto, nameof(dto));

            OperationResult result = await IdentityContract.SetOrganizationUsers(dto.OrganizationId, dto.OrganizationUsers);
            return result.ToAjaxResult();
        }
        #endregion
        #region "设置组织机构角色"
        /// <summary>
        /// 设置组织机构角色
        /// </summary>
        /// <param name="dto">组织机构角色信息</param>
        /// <returns>JSON操作结果</returns>
        [HttpPost]
        [ModuleInfo]
        [DependOnFunction(nameof(Read))]
        [DependOnFunction(nameof(ReadNode))]
        [DependOnFunction(nameof(ReadTreeNode))]
        [DependOnFunction(nameof(ReadRoleOrganizations))]
        [UnitOfWork]
        [Description("设置角色")]
        public virtual async Task<AjaxResult> SetRoles(OrganizationSetRoleDto dto)
        {
            Check.NotNull(dto, nameof(dto));

            OperationResult result = await IdentityContract.SetOrganizationRoles(dto.OrganizationId, dto.OrganizationRoles);
            return result.ToAjaxResult();
        }
        #endregion

        #endregion

        #region "受保护方法"
        #region "获取用户信息"
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="userRepository">用户仓储模型</param>
        /// <param name="userId">用户编号</param>
        /// <returns></returns>
        [NonAction]
        [NonFunction]
        protected static UserSimpleDto GetUser(IRepository<User, long> userRepository, long? userId)
        {
            if (userId == null)
            {
                return new UserSimpleDto();
            }
            
            var user = userRepository.QueryAsNoTracking(o => o.Id == userId).ToCacheFirst<User, UserSimpleDto>(10, false, nameof(UserSimpleDto));
            return user ?? new UserSimpleDto();
        }
        #endregion

        #region "转换组织机构角色用户节点为树形结构"
        /// <summary>
        /// 转换组织机构角色用户节点为树形结构
        /// </summary>
        /// <param name="node">组织机构角色用户节点</param>
        /// <param name="nodes">组织机构角色用户节点集合</param>
        /// <returns></returns>
        [NonAction]
        [NonFunction]
        protected virtual List<OrganizationRoleUserNode> ConvertOrganizationRoleUserNodeToTree(OrganizationRoleUserNode node, List<OrganizationRoleUserNode> nodes)
        {
            List<OrganizationRoleUserNode> child = new();
            var orgChilds = nodes.Where(o => node.Id == o.ParentId).OrderBy(m => m.OrderNo).ThenBy(m => m.Id).ToList();
            if (orgChilds != null)
            {
                foreach (var orgChild in orgChilds)
                {
                    var childNode = new OrganizationRoleUserNode
                    {
                        Id = orgChild.Id,
                        Type = orgChild.Type,
                        Name = orgChild.Name,
                        Description = orgChild.Description,

                        OrderNo = orgChild.OrderNo,
                        TreePathString = orgChild.TreePathString,

                        ParentId = orgChild.ParentId,
                        EnableLogin = orgChild.EnableLogin,
                        IsDefault = orgChild.IsDefault,
                        IsSystem = orgChild.IsSystem,
                        IsLocked = orgChild.IsLocked,
                        CreatedTime = orgChild.CreatedTime,
                        IsChecked = orgChild.IsChecked,
                        Administrator = orgChild.Administrator,
                        Leader = orgChild.Leader,
                    };
                    if (nodes.Exists(m => Equals(m.ParentId, childNode.Id)))
                    {
                        childNode.Items = ConvertOrganizationRoleUserNodeToTree(childNode, nodes);
                    }
                    child.Add(childNode);
                }
            }
            return child;
        }
        #endregion

        #endregion

    }

}
